#pragma once

#include <memory>
#include <vector>

#include <gl/glew.h>

#include "pickable.h"
#include "utility.h"

#include "gui/guimessage.h"

class Widget:public Pickable{
    public:
        Widget();

        virtual void AddChild(std::unique_ptr<Widget> child);
        void DestroyChildren();

        virtual std::string GetType() = 0;

        Widget* GetChild(std::string name);

        virtual void Draw();
        virtual void PreDraw();
        virtual void PostDraw();
        virtual void Pick();
        virtual void PrePick();
        virtual void PostPick();

        int GetWidth(){ return width; }
        int GetHeight(){ return height; }
        int NumChildren(){ return children.size(); }
        virtual GUIMessage* Click(int color);
        bool IsEnabled(){ return enabled; }
        std::string GetName(){ return name; }
        bool IsSelected(){ return selected; }

        int Getx(){ return x; }
        int Gety(){ return y; }
        int Getz(){ return z; }
        void Setx(int val){ x = val; }
        void Sety(int val){ y = val; }
        void Setz(int val){ z = val; }

        void Move(int dx, int dy){ x += dx; y += dy; }
        void SetHeight(int h);
        void SetWidth(int w);

        void SetSelected(bool sel){ selected = sel; }
        void SetGUIMessage(std::unique_ptr<GUIMessage> message){ clickedMessage = std::move(message); }

        bool IsHidden(){ return hidden; }
        void Hide(){ hidden = true; }
        virtual void Show(){ hidden = false; }
        void ToggleShow();
        void HideChildren(){ hideChildren = true; }
        void ShowChildren(){ hideChildren = false; }

        void Enable(bool enable=true){ enabled = enable; }
        void Disable(){ enabled = false; }

        void SetObscured(bool o){ obscured = o; }

        void SetName(std::string val){ this->name = val; }
        void SetTexture(GLuint val){ texture = val; }

        void SetParent(Widget* par){ parent = par; }
        Widget* GetParent(){ return parent; }

        virtual std::vector<Widget*> GetChildren();

        virtual void BuildVBO();
    protected:
        virtual GUIMessage* ProcessMessage(GUIMessage* message);

        void BuildVBO(int* vertices, int numVertices, float* uvs);

        bool hidden;
        bool hideChildren;
        bool enabled;
        bool selected;
        float bgColor[3];
        std::string name;
        std::unique_ptr<GUIMessage> clickedMessage;

        std::vector<std::unique_ptr<Widget>> children;
        Widget* parent;

        GLuint vertexVBO;
        GLuint colorVBO;
        GLuint uvVBO;
        GLuint pick_vao;
        GLuint drawVAO;
        GLint drawOffsetUniform;
        GLint pickOffsetUniform;
        GLint colorUniform;
        GLint obscurorUniform;
        GLuint texture;
        bool obscured;

        int x;
        int y;
        int z;
        int height;
        int width;

        int numVertices;
};
